package com.dinglian.ots.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.dinglian.ots.common.EncryptHelper;
import com.dinglian.ots.common.HttpRequest;
import com.dinglian.ots.common.ToolUtils;
import com.dinglian.ots.common.model.Constant;
import com.dinglian.ots.dao.mapper.StoreMapper;
import com.dinglian.ots.dao.mapper.UserMapper;
import com.dinglian.ots.dao.model.User;
import com.dinglian.ots.dao.model.UserExample;
import com.dinglian.ots.exception.GlobalException;
import com.dinglian.ots.redis.RedisService;
import com.dinglian.ots.redis.SessionKey;
import com.dinglian.ots.redis.UserKey;
import com.dinglian.ots.result.CodeMsg;
import com.dinglian.ots.service.BrandService;
import com.dinglian.ots.service.UserService;
import com.dinglian.ots.shiro.MyShiroToken;
import com.dinglian.ots.vo.user.BrandLoginVo;
import com.dinglian.ots.vo.user.LoginByPasswordVo;
import com.dinglian.ots.vo.user.LoginVo;
import com.dinglian.ots.vo.user.UserVo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.xmlbeans.impl.xb.ltgfmt.Code;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

/**
 * @author wangbo
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private BrandService brandService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private StoreMapper storeMapper;

    @Value("${brandUrl}")
    private String brandUrl;

    @Override
    public UserVo getUserByUserName(String username) {
        UserVo userVo = userMapper.getUserByUserName(username);
        if (userVo != null) {
            List<Map> brandList = userMapper.getUserBrandList(userVo.getUserId());
            List<Map> storeList = userMapper.getUserStoreList(userVo.getUserId());

            userVo.setBrandList(brandList);
            userVo.setStoreList(storeList);
        }
        String roleName = userVo.getRoleName();

        Integer userId = userVo.getUserId();
        String name = "";
        if (Constant.BUYER_ROLE_NAME.equals(roleName)) {
            name = userMapper.getStoreName(userId);
            userVo.setName(name);

            int status = storeMapper.isAudit(userId);
            if (status == 2) {
                userVo.setAudit(true);
            } else {
                userVo.setAudit(false);
            }
        } else if (Constant.BRAND_ROLE_NAME.equals(roleName)) {
            name = userMapper.getBrandName(userId);
            userVo.setName(name);
            userVo.setAudit(false);
        } else if (Constant.SHOWROOM_ROLE_NAME.equals(roleName)) {
            name = userMapper.getBrandName(userId);
            userVo.setName(name);
            userVo.setAudit(false);
        } else {
            userVo.setAudit(false);
        }
        return userVo;
    }

    private boolean isFirstSynchronize(String phone) {
        UserExample userExample = new UserExample();
        userExample.or().andUsernameEqualTo(phone);
        List<User> users = userMapper.selectByExample(userExample);
        if (users.isEmpty()) {
            return true;
        } else {
            User user = users.get(0);
            return user.getIsFirst();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public UserVo brandLogin(BrandLoginVo brandLoginVo) {
        String phone = brandLoginVo.getUsername();

        boolean isFirst = isFirstSynchronize(phone);
        if (isFirst) {
            //判断是否存在相同的手机号
            UserExample userExample = new UserExample();
            userExample.or().andUsernameEqualTo(phone);
            List<User> users = userMapper.selectByExample(userExample);
            if (!users.isEmpty()) {
                User user = users.get(0);
                if (Constant.BUYER_ROLE == user.getRoleId()) {
                    throw new GlobalException(CodeMsg.TO_BUYER_LOGIN);
                } else if (Constant.BRAND_ROLE == user.getRoleId() || Constant.SHOWROOM_ROLE == user.getRoleId()) {
                    throw new GlobalException(CodeMsg.USERNAME_IS_EXIST);
                }
            }


            String result = HttpRequest.sendPost(brandUrl, "phone=" + phone + "&mail=");
            result = ToolUtils.decodeUnicode(result);
            JSONObject jsonObject = JSONObject.parseObject(result);
            brandService.synchronizeBrandInfo(jsonObject, phone);
        }

        Subject subject = SecurityUtils.getSubject();
        MyShiroToken token = new MyShiroToken(brandLoginVo.getUsername(), brandLoginVo.getCode(), Constant.BRAND_ROLE);
        try {
            subject.login(token);
        } catch (AuthenticationException e) {
            throw new GlobalException(CodeMsg.CODE_ERROR);
        }
        UserVo userVo = (UserVo) subject.getPrincipal();
        return userVo;
    }

    @Override
    public void logout() {
        Subject subject = SecurityUtils.getSubject();
        Session session = subject.getSession();
        UserVo userVo = (UserVo) session.getAttribute(Constant.SESSION_USER);
        if (userVo != null) {
//            redisService.delete(SessionKey.getKey, userVo.getUserId() + "");
            redisService.delete(UserKey.getKey, userVo.getSessionToken());
        }
        subject.logout();
    }

    @Override
    public UserVo getUserInfoAgain(String sessionToken) {
        if (StrUtil.isBlank(sessionToken)) {
            throw new GlobalException(CodeMsg.INVALID_SESSION_TOKEN);
        }
        // 2.根据token获取用户信息
        UserVo user = redisService.get(UserKey.getKey, sessionToken, UserVo.class);
        if (user == null) {
            throw new GlobalException(CodeMsg.USER_NOT_LOGIN);
        }
        Session session = SecurityUtils.getSubject().getSession();
        session.setAttribute(Constant.SESSION_USER, user);

        return user;
    }
}
